#ifndef __TEMPLATE_DRIVER_H
#define __TEMPLATE_DRIVER_H

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/timer.h>
// 设备号操作
#include <linux/types.h>
#include <linux/kdev_t.h>
// device tree
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_address.h>
// interrupt
#include <linux/interrupt.h>
#include <linux/gpio.h>
// queue 
#include <linux/workqueue.h>
// misc
#include <linux/miscdevice.h>
// chardev device class
#include <linux/cdev.h>	
#include <linux/device.h> 
// 向应用层通知信息
#include <asm/siginfo.h>
#include <linux/pid.h>
#include <linux/uaccess.h>
#include <linux/sched/signal.h>

#define CHARDEV_NAME    		"template_name"	        // 定义设备名称 在/proc/devices下查看
#define DEVICE_NUMBER 			1		 		        // 定义次设备号的个数
#define DEVICE_MINOR_NUMBER 	0 				        // 定义次设备号的起始地址
#define DEVICE_CLASS_NAME 		"template_class" 	    // 在/sys/class下查看
#define DEVICE_NODE_NAME 		"template" 		        // 定义设备节点的名字 在/dev/下查看
#define Of_MATCH_COMPATILBLE    "licheepi, btns"   // 设备树compatilble属性
#define ID_TABLE_COMPATILBLE    "device_platform"       // id_table compatilble属性
#define INTERRUPT_NAME          "interrupt_irq_demo"    // 中断名
#define WORKQUEUE_NAME          "test work"             // 工作队列名

// 工作队列传参
struct work_data{
    struct work_struct  none_work;          // 普通工作项
    struct delayed_work  delay_work;        // 延时工作项
    char name[12];
    char data[12];
    int flag;
};

// 驱动结构体
struct driver_class{
    /* 设备号 */
    int major_num;  // 主设备号
    int minor_num;  // 次设备号
    dev_t dev_num;  // dev_t 是个 32 位的变量，其中 12 位用来表示主设备号，20 位用来表示次设备号 

    /* 设备树节点 */
    struct device_node *devicetree_node; 

    /* 字符设备结构体 */
    struct cdev chrdev;  

    /* 创建设备节点 */
    struct class *cls;        // 类 
    struct device *dev;       // 设备 

    /* 应用层pid */
    int app_pid;

    /* 定时器 */
    struct timer_list timer;

    /* 中断相关 */
    int irq_num;

    /* 中断下文 tasklet */
    struct tasklet_struct tasklet;

    /* 中断下文工作队列 */
    struct work_data work;                     // 工作项结构体
    struct workqueue_struct *work_queue;        // 工作队列 
};

enum IOCTL_ENUM{
    IOCTL_START = 0,
    IOCTL_SET_PID,
    IOCTL_END,   
};

#endif // __TEMPLATE_DRIVER_H